package com.mes.schedule.manager;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import com.mes.common.domain.BasicModel;
import com.mes.common.exception.bo.BaseBusinessException;
import com.mes.common.manager.BasicManager;
import com.mes.common.model.ObjectOperation;
import com.mes.common.util.IdentityGenerator;
import com.mes.schedule.domain.SDevice;
import com.mes.schedule.domain.SGroupOperationTask;
import com.mes.schedule.domain.SOperationLink;
import com.mes.schedule.domain.SOperationTask;
import com.mes.schedule.domain.SPartTask;
import com.mes.schedule.domain.SVirtualLink;
import com.mes.schedule.domain.ScheduleScheme;
import com.mes.schedule.manager.iface.IScheduleLinkManager;
import com.mes.schedule.dao.SOperationLinkDao;

@Component("scheduleLinkManager")
@Transactional
public class ScheduleLinkManager extends BasicManager implements IScheduleLinkManager{
	private final static Log log = LogFactory
			.getLog(ScheduleLinkManager.class);
	 
	private SOperationLinkDao SOperationLinkDao;

	public ScheduleLinkManager() {
		super();
		//this.setObjectName(SOperationLink.class.getName());

	}

	public SOperationLink getLink(ScheduleScheme scheme, SOperationTask predSo,
			SOperationTask succSo) {
		String linkKey = predSo.getTaskUid() + "__" + succSo.getTaskUid();
		return scheme.getAllOperationLinkMap().get(linkKey);
	}

	public SOperationLink getLink(ScheduleScheme scheme, String predSoUid,
			String succSoUid) {
		String linkKey = predSoUid + "__" + succSoUid;
		return scheme.getAllOperationLinkMap().get(linkKey);
	}

	public void init() {
		this.setBasicDao(SOperationLinkDao);
	}

	public void addLink(SOperationTask predSo, SOperationTask succSo,
			int linkType, int linkLag) throws Exception {

		ScheduleScheme scheme = predSo.getScheme();
		SOperationLink link = new SOperationLink();
		link.setPredOperationTask(predSo);
		link.setSuccOperationTask(succSo);
		link.setLinkType(linkType);
		link.setLinkLag(linkLag);
		link.setLinkUid(IdentityGenerator.GetIdentityString());
		link.setScheme(scheme);

		addLink(link);

		link = null;
	}

	public void deleteLink(SOperationLink link) {
		// TODO Auto-generated method stub
		if (link == null)
			return;
		try {
			// Iterator<SOperationLink>
			// iterator=link.getPredOperationTask().getSuccLinkSet().iterator();
			// while(iterator.hasNext())
			// {
			// SOperationLink oLink=iterator.next();
			// if(oLink.getLinkKey().equals(link.getLinkKey()))
			// {
			// iterator.remove();
			// break;
			// }
			// }
			// iterator=link.getSuccOperationTask().getPredLinkSet().iterator();
			// while(iterator.hasNext())
			// {
			// SOperationLink oLink=iterator.next();
			// if(oLink.getLinkKey().equals(link.getLinkKey()))
			// {
			// iterator.remove();
			// break;
			// }
			// }

			if (log.isDebugEnabled()) {
				if (link.getPredOperationTask().getTaskUid().equals(
						"8404402d-33ef-4e6a-9014-b43501261a36")
						&& link.getSuccOperationTask().getTaskUid().equals(
								"1befb5b5-386b-4922-b70f-20bceb188e79")) {
					log.debug(link.getPredOperationTask());
				}
			}

			link.getPredOperationTask().getSuccLinkSet().remove(link);
			link.getSuccOperationTask().getPredLinkSet().remove(link);

			link.getScheme().getAllOperationLinkMap().remove(link.getLinkKey());
			if (link.isPersistence()) {
				this.delete(link);
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();

		}

		// SOperationTask predSo=link.getPredOperationTask();
		// SOperationTask succSo=link.getSuccOperationTask();
		//		
		// Set<SOperationLink> linkSet=predSo.getSuccLinkSet();
		// linkSet.remove(link);
		// predSo.setSuccLinkSet(linkSet);
		//		
		// linkSet=succSo.getPredLinkSet();
		// linkSet.remove(link);
		// succSo.setPredLinkSet(linkSet);

	}

	/*
	 * 删除某一个工序任务的所有前置任务 (non-Javadoc)
	 * 
	 * @see com.mes.schedule.manager.iface.ScheduleLinkManager#deletePredLink(com.mes.schedule.persistence.domain.SOperationTask)
	 */
	public void deletePredLink(SOperationTask so) {
		// TODO Auto-generated method stub
		if (so.getPredLinkSet() == null || so.getPredLinkSet().size() == 0)
			return;

		List<SOperationLink> deletedLinks = new ArrayList<SOperationLink>();
		deletedLinks.addAll(so.getPredLinkSet());

		for (SOperationLink link : deletedLinks) {
			this.deleteLink(link);

		}
	}

	public void deleteSuccLink(SOperationTask so) {
		// TODO Auto-generated method stub
		if (so.getSuccLinkSet() == null || so.getSuccLinkSet().size() == 0)
			return;

		List<SOperationLink> deletedLinks = new ArrayList<SOperationLink>();
		deletedLinks.addAll(so.getSuccLinkSet());

		for (SOperationLink link : deletedLinks) {
			this.deleteLink(link);

		}

	}

	// 经典程序备份
	// public boolean isPredTask(SOperationTask predTask,SOperationTask
	// succTask) throws Exception
	// {
	//		
	// for(SOperationLink succLink:predTask.getSuccLinkSet())
	// {
	// if(succLink.getSuccOperationTask().equals(succTask))
	// return true;
	// //对组任务的判断
	// //如果succTask是一个组，并且后续任务在这个组中，也属于前置链接
	// if(succTask instanceof SGroupOperationTask)
	// {
	// SGroupOperationTask groupOperationTask=(SGroupOperationTask)succTask;
	// if(groupOperationTask.isInGroup(succLink.getSuccOperationTask()))
	// return true;
	// }
	// if(isPredTask(succLink.getSuccOperationTask(),succTask))
	// return true;
	// }
	// return false;
	// }
	public boolean isPredTask(SOperationTask predTask, SOperationTask succTask)
			throws Exception {
		if (predTask.equals(succTask))
			return true;
		Map<String, SOperationTask> trackMap = new HashMap<String, SOperationTask>();
		boolean b = this.isPredTaskSafe(predTask, succTask, trackMap);
		if (log.isDebugEnabled())

		{

			// if (b) {
			// StringBuilder s = new StringBuilder();
			// this.printCyclePath(predTask, succTask, s);
			// log.info(s.toString());
			// }
		}

		return b;

	}

	private boolean printCyclePath(SOperationTask predTask,
			SOperationTask succTask, StringBuilder trackPath) {

		log.debug(predTask.toFriendlyString());
		if (trackPath.toString().contains(predTask.toString())) {
			// 也让它将最后一个循环加上
			trackPath.append(predTask.toString() + "\n");
			log.info(trackPath.toString());
			return true;
		}
		// 也让它将最后一个循环加上
		trackPath.append(predTask.toString() + "工序深度为："
				+ predTask.getNetDepth() + "\n");
		log.debug("前置任务数量：" + predTask.getPredLinkSet().size() + "，后置任务数量："
				+ predTask.getSuccLinkSet().size());
		StringBuilder newTrackPath;
		for (SOperationLink succLink : predTask.getSuccLinkSet()) {
			boolean b = false;
			SOperationTask succOperationTask = succLink.getSuccOperationTask();

			if (succOperationTask.getTaskUid().equals(
					"e5c14af7-da47-4ac0-a2f8-72d0ae5f76ef")) {
				log.info(succOperationTask.getNetDepth());
			}

			if (succOperationTask.equals(succTask))
				b = true;
			// 对组任务的判断
			// 如果succTask是一个组，并且后续任务在这个组中，也属于前置链接
			if (succTask instanceof SGroupOperationTask) {
				SGroupOperationTask groupOperationTask = (SGroupOperationTask) succTask;
				if (groupOperationTask.isInGroup(succOperationTask))
					b = true;
			}

			if (b) {
				// 也让它将最后一个循环加上
				trackPath.append(succOperationTask.toString() + "工序深度为："
						+ succOperationTask.getNetDepth() + "\n");
				log.info(trackPath.toString());
				return true;
			}
			try {
				// 保证找到正确的分支
				if (predTask.getSuccLinkSet().size() == 1
						|| this.isPredTask(succOperationTask, succTask)) {
					newTrackPath = new StringBuilder();
					newTrackPath.append(trackPath.toString());
					if (printCyclePath(succOperationTask, succTask,
							newTrackPath))
						return true;

					break;
				}
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

		return false;
	}

	// 避免循环链接导致堆栈溢出
	private boolean isPredTaskSafe(SOperationTask predTask,
			SOperationTask succTask, Map<String, SOperationTask> trackMap)
			throws Exception {
		if (trackMap.containsKey(predTask.getTaskUid())) {

			// log.warn("调度链接中可能出现循环链接," + predTask.toFriendlyString());
			// if(log.isDebugEnabled())
			// {
			// StringBuilder trackPath=new StringBuilder();
			//				
			// //printCyclePath(predTask,predTask,trackPath);
			//				
			// for(SOperationTask trackOp:trackMap.values())
			// {
			// //log.warn(trackOp.toFriendlyString());
			// }
			// }
			return false;
		} else {
			trackMap.put(predTask.getTaskUid(), predTask);
		}

		for (SOperationLink succLink : predTask.getSuccLinkSet()) {
			if (succLink.getSuccOperationTask().equals(succTask))
				return true;
			// 对组任务的判断
			// 如果succTask是一个组，并且后续任务在这个组中，也属于前置链接
			if (succTask instanceof SGroupOperationTask) {
				SGroupOperationTask groupOperationTask = (SGroupOperationTask) succTask;
				if (groupOperationTask.isInGroup(succLink
						.getSuccOperationTask()))
					return true;
			}
			if (isPredTaskSafe(succLink.getSuccOperationTask(), succTask,
					trackMap))
				return true;
		}
		return false;
	}

	public void cycleLinkCheck(SOperationTask predTask, SOperationTask succTask)
			throws Exception {
		if (predTask == succTask)
			throw new Exception("工序链接出现循环递归定义！");
		for (SOperationLink succLink : predTask.getSuccLinkSet()) {
			cycleLinkCheck(succLink.getSuccOperationTask(), succTask);
		}
	}

	/**
	 * 计算后道工序开始时间相对前道工序的延迟 计算平顺移动时，并未考虑链接的延迟数量， 因为我们在计算平顺移动时，考虑了最早完成时间，
	 * 然后由最早完成时间倒推起始时间，实现了一种考虑日历情况下的平顺
	 */
	public long calPSLag(SOperationLink link) {
		return this.calPSLagMinutes(link) * 60000;
	}

	/**
	 * 计算流水加工下的延迟
	 * 
	 * @param link
	 * @return
	 */
	public long calFlowLag(SOperationLink link) {
		return this.calFlowLagMinutes(link) * 60000;
	}

	public void saveLink(ScheduleScheme scheme, List<SOperationLink> slinkList)
			throws Exception {
		for (SOperationLink slink : slinkList) {
			if (slink.getObjectState() == BasicModel.OBJECTSTATE_TOBEDELETED) {
				// removeOperationLink(scheme, slink.getTaskUid());
			} else {

				if (slink.getObjectState() == BasicModel.OBJECTSTATE_TOBEADDED) {
					// addOperationLink(scheme, slink, partTask);

				} else if (slink.getObjectState() == BasicModel.OBJECTSTATE_TOBEUPDATED) {
					updateLink(scheme, slink);
				}

			}

		}

	}

	public List<SOperationLink> getPartOperationLink(ScheduleScheme scheme,
			String partTaskUid) throws Exception {
		if (partTaskUid == null)
			return null;
		SPartTask partTask = scheme.getAllPartTaskMap().get(partTaskUid);
		if (partTask == null) {
			log.warn("无法找到对应零件任务：" + partTaskUid);
			return null;
		}
		List<SOperationLink> linkList = new ArrayList<SOperationLink>();

		for (SOperationTask so : partTask.getOperationTaskList()) {

			for (SOperationLink sl : so.getSuccLinkSet()) {
				linkList.add(sl);

			}

		}
		return linkList;
	}

	public void updateLink(ScheduleScheme scheme, SOperationLink newLink) {
		// TODO Auto-generated method stub
		// 20130812,用linkkey避免重复

		SOperationLink oldLink = scheme.getAllOperationLinkMap().get(
				newLink.getLinkKey());
		oldLink.setMoveType(newLink.getMoveType());
		oldLink.setTransferQty(newLink.getTransferQty());
		oldLink.setLinkLag(newLink.getLinkLag());
		oldLink.setLocked(newLink.getLocked());
		if (oldLink.isPersistence()) {
			try {
				this.update(oldLink);
			} catch (BaseBusinessException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

	}

	 
	public void addLink(SOperationLink link) throws Exception {
		try {
			if (link.getPredOperationTask() == null
					|| link.getSuccOperationTask() == null)
				return;
			if (link.getScheme() == null)
				link.setScheme(link.getPredOperationTask().getScheme());
			ScheduleScheme scheme = link.getScheme();

			if (log.isDebugEnabled()) {

				if (link.getSuccOperationTask().getTaskUid().equals(
						"29d7e392-3c1e-4757-a0c7-c2672a6ed99c")) {
					log.debug(link.getPredOperationTask());
				}
			}

			// 不允许虚拟链接添加时 覆盖原有的 实际链接
			// 也是为了防止虚拟链接的加入 覆盖掉原来本存在的工序链接
			if (scheme.getAllOperationLinkMap().containsKey(link.getLinkKey())) {
				SOperationLink oLink = scheme.getAllOperationLinkMap().get(
						link.getLinkKey());
				if (!oLink.getVirtualLink() && link.getVirtualLink())
					return;

			}

			// TODO Auto-generated method stub
			// TODO Auto-generated method stub
			SOperationTask predSo = link.getPredOperationTask();
			SOperationTask succSo = link.getSuccOperationTask();
			if (predSo == null || succSo == null)
				return;
			// if(predSo==succSo)
			// throw new Exception("前置工序不能与后置工序相同！");

			// 出现一次错误，前置工序与后置工序相同
			// 导致同步时不停转
			// 同步不了，需要解决
			if (predSo == succSo) {
				log.warn("严重警告，前置工序不能与后置工序相同！");
				return;
			}
			// //循环递归判断

			// //循环递归判断
			// 由于可能同时在一次操作中执行多次链接创建与删除操作，
			// 所以这种判断反而是无意义的了
			// cycleLinkCheck(succSo,predSo);

			if (link.getLinkUid() == null)
				link.setLinkUid(IdentityGenerator.GetIdentityString());
			if (link.getLinkType() == null)
				link.setLinkType(SOperationLink.LINKTYPE_FTS);
			if (link.getLinkLag() == null)
				link.setLinkLag(0);

			predSo.getSuccLinkSet().add(link);
			succSo.getPredLinkSet().add(link);
			// 20130812,用linkkey避免重复
			scheme.getAllOperationLinkMap().put(link.getLinkKey(), link);
			if (link.isPersistence())
				this.add((SOperationLink) link);

			// Set<SOperationLink> linkSet=predSo.getSuccLinkSet();
			// linkSet.add(link);
			// predSo.setSuccLinkSet(linkSet);
			//		
			//		
			// linkSet=succSo.getPredLinkSet();
			// linkSet.add(link);
			// succSo.setPredLinkSet(linkSet);

			link = null;
		} catch (RuntimeException e) {
			// TODO Auto-generated catch block
			log.error("添加工序任务链接关系发生错误!", e);
			throw e;
		}
	}

	 
	public void addVirtualLink(SVirtualLink link) throws Exception {
		if (link.getPredOperationTask() == null
				|| link.getSuccOperationTask() == null)
			return;

		if (log.isDebugEnabled()) {
			if (link.getPredOperationTask().getTaskUid().equals("4048883")) {
				log.debug(link.getPredOperationTask());
			}
		}

		if (link.getScheme() == null)
			link.setScheme(link.getPredOperationTask().getScheme());
		ScheduleScheme scheme = link.getScheme();

		// 不允许虚拟链接添加时 覆盖原有的 实际链接
		// 也是为了防止虚拟链接的加入 覆盖掉原来本存在的工序链接
		if (scheme.getAllOperationLinkMap().containsKey(link.getLinkKey())) {
			SOperationLink oLink = scheme.getAllOperationLinkMap().get(
					link.getLinkKey());
			if (!oLink.getVirtualLink())
				return;

		}

		// 放在这里效率比较低，
		// 应该有一个全局的网络链接环路检查方法，暂时只对虚拟链接起作用
		// lqm todo
		if (this.isPredTask(link.getSuccOperationTask(), link
				.getPredOperationTask()))// 注意这里succso,predso的顺序
		{
			// lqm todo
			// 应该打印前置任务链条，
			// 抛到界面
			// 让用户看见

			log.warn("虚拟链接出现环路！"
					+ link.getSuccOperationTask().toFriendlyString()
					+ " 已经是任务 "
					+ link.getPredOperationTask().toFriendlyString()
					+ " 的前置任务 "

			);
			if (log.isDebugEnabled()) {

				StringBuilder s = new StringBuilder();
				this.printCyclePath(link.getSuccOperationTask(), link
						.getPredOperationTask(), s);
				// log.info(s.toString());

				// this.printCyclePath(SOperationTask, SOperationTask,
				// StringBuilder)

			}

			return;
		}

		this.addLink(link);

		link = null;
	}

	 
	public List<SOperationLink> getDeviceOperationLink(ScheduleScheme scheme,
			String deviceUid) throws Exception {
		if (deviceUid == null)
			return null;
		SDevice device = scheme.getDeviceMap().get(deviceUid);
		if (device == null) {
			log.warn("无法找到对应设备：" + deviceUid);
			return null;
		}
		List<SOperationLink> linkList = new ArrayList<SOperationLink>();

		for (SOperationTask so : scheme.getScheduleOperationTasks()) {
			if (so.getDeviceUid() != null
					&& so.getDeviceUid().equals(deviceUid)
					&& so.getGroupTask() == null) {
				for (SOperationLink sl : so.getSuccLinkSet()) {
					if (sl instanceof SVirtualLink) {
						SVirtualLink dl = (SVirtualLink) sl;
						if (dl.isPersistence() && (!linkList.contains(sl)))
							linkList.add(sl);

					}

				}
				for (SOperationLink sl : so.getPredLinkSet()) {
					if (sl instanceof SVirtualLink) {
						SVirtualLink dl = (SVirtualLink) sl;
						if (dl.isPersistence() && (!linkList.contains(sl)))
							linkList.add(sl);

					}

				}
			}
		}
		return linkList;
	}

	 
	public void saveVirtualLink(ScheduleScheme scheme,
			List<SVirtualLink> slinkList) throws Exception {
		for (SVirtualLink slink : slinkList) {
			if (slink.getObjectState() == BasicModel.OBJECTSTATE_TOBEDELETED) {
				SOperationLink olink = scheme.getAllOperationLinkMap().get(
						slink.getLinkKey());
				this.deleteLink(olink);

			} else {

				if (slink.getObjectState() == BasicModel.OBJECTSTATE_TOBEADDED) {

					SVirtualLink newLink = new SVirtualLink();
					newLink.setScheme(scheme);
					String taskUid = slink.getPredecessorUid();
					if (taskUid != null) {
						newLink.setPredecessorUid(taskUid);
						newLink.setPredOperationTask(scheme
								.getAllOperationTaskMap().get(taskUid));
					}
					taskUid = slink.getSuccessorUid();
					if (taskUid != null) {
						newLink.setSuccessorUid(taskUid);
						newLink.setSuccOperationTask(scheme
								.getAllOperationTaskMap().get(taskUid));
					}
					newLink.setPersistence(true);
					newLink.setMoveType(slink.getMoveType());
					this.addVirtualLink(newLink);
					// addOperationLink(scheme, slink, partTask);

				} else if (slink.getObjectState() == BasicModel.OBJECTSTATE_TOBEUPDATED) {
					// lqm todo
					// 这里对update的处理是存在bug的
					// 万一计划员修改predtaskuid或者succtaskuid怎么办

					SVirtualLink olink = (SVirtualLink) scheme
							.getAllOperationLinkMap().get(slink.getLinkKey());
					if (olink != null) {
						olink.setMoveType(slink.getMoveType());
						olink.setTransferQty(slink.getTransferQty());
						olink.setLinkLag(slink.getLinkLag());
						olink.setLocked(slink.getLocked());
						olink.setPersistence(true);
					}
				}

			}

		}

	}

	public SOperationLinkDao getScheduleOperationLinkDao() {
		return SOperationLinkDao;
	}

	public void setScheduleOperationLinkDao(
			SOperationLinkDao SOperationLinkDao) {
		this.SOperationLinkDao = SOperationLinkDao;
	}

	 
	public Boolean delete(Serializable object) throws BaseBusinessException {
		SOperationLink link = (SOperationLink) object;

		try {
			/*
			 * if (link.getUuid() != null) { SOperationLink persistenceLink =
			 * this.SOperationLinkDao .getById(link.getLinkUid()); if
			 * (persistenceLink != null) { super.delete(persistenceLink); } }
			 */
			if (link.getUuid() != null) {
				List<SOperationLink> linkList = this.SOperationLinkDao
						.findByProperty("linkUid", link.getLinkUid());
				for (SOperationLink persistenceLink : linkList) {
					super.delete(persistenceLink);
				}
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return true;
	}

	 
	public Boolean update(Serializable object) throws BaseBusinessException {
		SOperationLink link = (SOperationLink) object;

		try {
			SOperationLink persistenceLink = this.SOperationLinkDao
					.getById(link.getLinkUid());
			if (persistenceLink != null) {
				ObjectOperation.copyAttributes(link, persistenceLink, true);
				super.update(persistenceLink);
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return true;
		// return super.update(object);
	}

	//by lcs
	//将Boolean改为void
	public void add(Serializable object) throws Exception {
		SOperationLink persistenceLink = new SOperationLink();

		ObjectOperation.copyAttributes(object, persistenceLink);
		super.add(persistenceLink);

	}

	 
	public long calPSLagMinutes(SOperationLink link) {
		long temp = 0;
		try {
			SOperationTask predSo = link.getPredOperationTask();
			SOperationTask succSo = link.getSuccOperationTask();
			// 平顺时的最小批量f
			int transferCount = (link.getTransferQty() == null || link
					.getTransferQty() <= 0) ? 1 : link.getTransferQty();

			// 对完成数量大于0的情况未做充分考虑
			// 未考虑平顺数量的自动计算
			// 应该考虑完成数量大于0的情况
			// lqm todo
			double predEstiPreTime = predSo.getEstiPreTime();

			int lagCount = transferCount;
			if (predSo.getCompleteQty() != null && predSo.getCompleteQty() > 0) {
				predEstiPreTime = 0;
				lagCount = transferCount - predSo.getCompleteQty().intValue();

				if (lagCount < 0)
					lagCount = 0;

			}

			if (predSo.getEstiRunTime() <= succSo.getEstiRunTime()) {

				temp = (long) (predEstiPreTime + predSo.getEstiRunTime()
						* lagCount - succSo.getEstiPreTime());

			} else {
				temp = (long) (predSo.getEstiTaskWork()
						+ succSo.getEstiRunTime() * lagCount - succSo
						.getEstiTaskWork());
			}
			if (predSo.getEstiRunTime() == 0 && temp < 0)// 这种情况下用户完全用准备时间用作延搁时间
			{
				temp = 0;
			}

			if (predSo.getEstiDelayTime() != null
					&& predSo.getEstiDelayTime() > 0)
				temp += predSo.getEstiDelayTime().longValue();

		} catch (RuntimeException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return temp;
	}

	 
	public long calFlowLagMinutes(SOperationLink link) {

		long temp = 0;
		try {
			SOperationTask predSo = link.getPredOperationTask();
			SOperationTask succSo = link.getSuccOperationTask();

			double predEstiPreTime = predSo.getEstiPreTime();
			double qty = link.getTransferQty();
			if (link.getPredOperationTask().getTransferBatchQty() != null) {
				qty = link.getPredOperationTask().getTransferBatchQty();

			}

			qty = (qty <= 0) ? 1 : qty;

			link.setTransferQty((int) qty);

			// 解决430的转运批量问题

			// int
			// operationId=Integer.valueOf(link.getPredOperationTask().getOperationIdDesc());
			// if(operationId<40)
			// transferCount=100;
			// else if(operationId<105)
			// transferCount=50;
			// else if(operationId>=105)
			// transferCount=200;
			// if(transferCount>predSo.getPlanQty())transferCount=(int)Math.round(predSo.getPlanQty());

			// double qty=link.getPredOperationTask().getTransferBatchQty();
			// link.setTransferQty((int)qty);

			int lagCount = link.getTransferQty();
			if (predSo.getCompleteQty() != null && predSo.getCompleteQty() > 0) {
				predEstiPreTime = 0;
				lagCount = link.getTransferQty()
						- predSo.getCompleteQty().intValue();

				if (lagCount < 0)
					lagCount = 0;

			}

			// temp = (long) (predEstiPreTime + (predSo.getEstiRunTime()
			// * lagCount - succSo.getEstiPreTime()));
			// add by zy
			temp = (long) (predEstiPreTime + (predSo.getEstiRunTime() * lagCount));

			if (predSo.getEstiRunTime() == 0 && temp < 0)// 这种情况下用户完全用准备时间用作延搁时间
			{
				temp = 0;
			}

			if (predSo.getEstiDelayTime() != null
					&& predSo.getEstiDelayTime() > 0)
				temp += predSo.getEstiDelayTime().longValue();
		} catch (RuntimeException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return temp;
	}

	 
	public List<SOperationLink> getAssembleLink(ScheduleScheme scheme,
			String taskUid) throws Exception {

		List<SOperationLink> linkList = new ArrayList<SOperationLink>();

		for (SOperationLink sl : scheme.getAllOperationLinkMap().values()) {
			if (sl.getDependType() != null && sl.getDependType().equals(2)) {
				linkList.add(sl);

			}

		}

		return linkList;
	}
}